
package data_queuing;

import thes2sim.Frame;
import thes2sim.*;

import com.aliasi.util.BoundedPriorityQueue;
import java.io.IOException;
import java.util.Comparator;
import java.util.logging.Level;
import java.util.logging.Logger;

public class QueuingOrig {
    
    private Comparator<Frame> comparator = new PriorityComparator();
    BoundedPriorityQueue<Frame> dataqueue;

    Logging l = new Logging(0);
    
    int time;
        
    public QueuingOrig () {
        
        dataqueue = new BoundedPriorityQueue<Frame>(comparator, Util.queueSize);
       
    }
    
    public void printQContent() {
       
       Frame f;
      
       while(!dataqueue.isEmpty()) {
           f = dataqueue.remove();
           logAction(f, 4);
       }
    
    }
    
    public Frame transmitFrame(int simTime) {
        
        Frame f = null;
        this.time = simTime;
        
        if(!dataqueue.isEmpty()){
            f = dataqueue.remove();               
        }
        
        // Set exit time of frame
        if(f != null) {
            f.setExtTime(time);
            logAction(f, 3); 
        }
        
        
        
        return f;
    }
    
    public void queuePDU (PDU u, int id, int simTime) {
    
        Frame f = new Frame(u, id);
        
        this.time = simTime; 
        f.setEntTime(time);
        
        logAction(f, 1);
        dataqueue.offer(f);
        
        if(dataqueue.size() >= dataqueue.maxSize()) {
            Frame discarded = dataqueue.last();
            discarded.setDiscTime(time);
            logAction(discarded, 2);
            dataqueue.remove(discarded);
        }

    }
    
    private class PriorityComparator implements Comparator<Frame> {

        public int compare(Frame x, Frame y) {
            
            if(x.isServicing()) {
                return 1;
            }
            
            // 1 = High, 2 = Mid, 3 = Low
            if (x.getPayload().getPriority() > y.getPayload().getPriority()) {
                return -1;
            }
            
            if (x.getPayload().getPriority() < y.getPayload().getPriority()) {
                return 1;
            }
            
            if(x.getPayload().getTimecreate() < y.getPayload().getTimecreate()) {
                return 1;
            }
            
            if(x.getPayload().getTimecreate() > y.getPayload().getTimecreate()) {
                return -1;
            }
        
            return 0;
        }
    }
    
    // 1 - inserted frame
    // 2 - discard frame
    // 3 - transmitted frame
    // 4 - queue content
    
    public void logAction(Frame f, int type) {
        
        try {
           
            switch(type){
                
                case 1:
                    l.logActivity(
                        time + ", " 
                        + "Frame Insert, " 
                        + f.getId() + ", "
                        + f.getPayload().getPriority() + ", "
                        + f.getPayload().getTimecreate(), 1);
                    
                    l.logActivity(f.getId() + ", " 
                                + f.getPayload().getPriority() + ", " 
                                + f.getEntTime(), 2);
                    break;
                    
                case 2:
                    l.logActivity(
                        time + ", " 
                        + "Frame Discarded, " 
                        + f.getId() + ", "
                        + f.getPayload().getPriority() + ", "
                        + f.getPayload().getTimecreate(), 1);
                    
                    l.logActivity(f.getId() + ", " 
                                + f.getPayload().getPriority() + ", " 
                                + f.getEntTime() + ", " 
                                + f.getDiscTime(), 3);
                    break;
                    
                case 3:
                    l.logActivity(
                        time + ", " 
                        + "Frame Transmitted, " 
                        + f.getId() + ", "
                        + f.getPayload().getPriority() + ", "
                        + f.getPayload().getTimecreate(), 1);
                    
                    l.logActivity(f.getId() + ", " 
                                + f.getPayload().getPriority() + ", " 
                                + f.getEntTime() + ", " 
                                + f.getExtTime(), 4);
                    break;
                    
                case 4:
                    l.logActivity(f.getId() + ", " 
                                + f.getPayload().getPriority(), 5);
                    break;

            }
            
        } catch (IOException ex) {
            Logger.getLogger(QueuingOrig.class.getName()).log(Level.SEVERE, null, ex);
        }
       

    }
    
}
